import tkinter as tk
from tkinter import ttk, messagebox

from controllers.network_config_controller import NetworkConfigController
from models.network_config_model import NetworkConfigModel


class NetworkConfigView:
    """统一网络配置视图 - 支持独立窗口和内嵌模式"""

    def __init__(self, parent, container=None):
        """
        初始化网络配置视图
        :param parent: 父窗口（用于独立模式）
        :param container: 内嵌模式的容器（可选）
        """
        # 初始化MVC组件
        self.model = NetworkConfigModel()
        self.controller = NetworkConfigController(self.model)

        # 根据是否提供容器决定使用独立窗口还是内嵌模式
        if container:
            # 内嵌模式
            self.frame = ttk.Frame(container)
            self.frame.pack(fill=tk.BOTH, expand=True)
            self.create_widgets(self.frame)
        else:
            # 独立窗口模式
            self.top = tk.Toplevel(parent)
            self.top.title("网络配置设置")
            self.top.geometry("1024x1024")
            self.top.transient(parent)
            self.top.grab_set()
            self.top.resizable(True, True)
            self.frame = self.top
            self.create_widgets(self.top)
            self.center_window()

        # 绑定鼠标事件
        self.bind_mousewheel()

    def create_widgets(self, parent):
        """创建界面控件"""
        # 创建带滚动条的主框架
        container = ttk.Frame(parent)
        container.pack(fill=tk.BOTH, expand=True)

        # 创建Canvas和滚动条（仅在内嵌模式时创建）
        self.canvas = tk.Canvas(container)
        scrollbar = ttk.Scrollbar(
            container, orient="vertical", command=self.canvas.yview
        )
        self.scrollable_frame = ttk.Frame(self.canvas)

        self.scrollable_frame.bind(
            "<Configure>",
            lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all")),
        )

        self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
        self.canvas.configure(yscrollcommand=scrollbar.set)

        # 打包组件
        self.canvas.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")

        # 创建主框架（放在滚动区域内）
        main_frame = ttk.Frame(self.scrollable_frame, padding=20)
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 标题
        ttk.Label(main_frame, text="网络配置设置", font=("Arial", 16, "bold")).pack(
            pady=(0, 25), anchor=tk.W
        )

        # 内网配置区域
        internal_frame = ttk.LabelFrame(main_frame, text="内网配置")
        internal_frame.pack(fill=tk.BOTH, pady=15, expand=True, ipady=30, ipadx=10)
        self.create_network_config(internal_frame, "internal", self.model.get_config("internal"))

        # 分隔线
        ttk.Separator(main_frame, orient=tk.HORIZONTAL).pack(fill=tk.X, pady=15)

        # 外网配置区域
        external_frame = ttk.LabelFrame(main_frame, text="外网配置")
        external_frame.pack(fill=tk.BOTH, pady=15, expand=True)
        self.create_network_config(external_frame, "external", self.model.get_config("external"))

        # 按钮区域
        btn_frame = ttk.Frame(main_frame)
        btn_frame.pack(fill=tk.X, pady=20)

        # 添加保存按钮
        save_btn = tk.Button(
            btn_frame,
            text="保存设置",
            bg="#4CAF50",  # 设置背景色
            fg="white",  # 设置文字颜色
            font=("Arial", 10, "bold"),
            padx=15,  # 增加水平内边距
            pady=8,  # 增加垂直内边距
            command=self.save_all_configs,
        )
        save_btn.pack(side=tk.RIGHT, padx=10)

        # 添加取消按钮（仅独立窗口模式显示）
        if not hasattr(self, "top"):
            # 内嵌模式添加关闭按钮
            close_btn = tk.Button(
                btn_frame, text="关闭", padx=15, pady=8, command=self.close_view
            )
            close_btn.pack(side=tk.RIGHT)
        else:
            # 独立窗口模式显示取消按钮
            cancel_btn = tk.Button(
                btn_frame, text="取消", padx=15, pady=8, command=self.close_view
            )
            cancel_btn.pack(side=tk.RIGHT)

    def create_network_config(self, parent, network_type, config):
        """创建网络配置部分"""
        # 配置类型选择
        config_type_frame = ttk.Frame(parent)
        config_type_frame.pack(fill=tk.X, pady=5)

        dhcp_var = tk.BooleanVar(value=config.get("dhcp", True))
        setattr(self, f"{network_type}_dhcp_var", dhcp_var)

        ttk.Label(config_type_frame, text="配置类型:").pack(side=tk.LEFT, padx=(0, 10))

        ttk.Radiobutton(
            config_type_frame,
            text="自动获取IP地址(DHCP)",
            variable=dhcp_var,
            value=True,
            command=lambda: self.toggle_config_fields(network_type),
        ).pack(side=tk.LEFT, padx=(0, 15))

        ttk.Radiobutton(
            config_type_frame,
            text="手动配置IP地址",
            variable=dhcp_var,
            value=False,
            command=lambda: self.toggle_config_fields(network_type),
        ).pack(side=tk.LEFT)

        # 静态IP配置区域
        static_frame = ttk.LabelFrame(parent, text="IP设置")
        static_frame.pack(fill=tk.X, pady=10, expand=True)

        # 输入框宽度
        entry_width = 35
        label_width = 12
        frame_pack_pady = 8
        entry_pack_padx = 10

        # IP地址
        ip_frame = ttk.Frame(static_frame)
        ip_frame.pack(fill=tk.X, pady=frame_pack_pady)
        ttk.Label(ip_frame, text="IP地址:", width=label_width).pack(side=tk.LEFT)
        ip_entry = ttk.Entry(ip_frame, width=entry_width)
        ip_entry.pack(side=tk.LEFT, padx=entry_pack_padx, fill=tk.X, expand=True)
        ip_entry.insert(0, config.get("ip", ""))
        setattr(self, f"{network_type}_ip_entry", ip_entry)

        # 子网掩码
        mask_frame = ttk.Frame(static_frame)
        mask_frame.pack(fill=tk.X, pady=frame_pack_pady)
        ttk.Label(mask_frame, text="子网掩码:", width=label_width).pack(side=tk.LEFT)
        mask_entry = ttk.Entry(mask_frame, width=entry_width)
        mask_entry.pack(side=tk.LEFT, padx=entry_pack_padx, fill=tk.X, expand=True)
        mask_entry.insert(0, config.get("mask", "255.255.255.0"))
        setattr(self, f"{network_type}_mask_entry", mask_entry)

        # 默认网关
        gateway_frame = ttk.Frame(static_frame)
        gateway_frame.pack(fill=tk.X, pady=frame_pack_pady)
        ttk.Label(gateway_frame, text="默认网关:", width=label_width).pack(side=tk.LEFT)
        gateway_entry = ttk.Entry(gateway_frame, width=entry_width)
        gateway_entry.pack(side=tk.LEFT, padx=entry_pack_padx, fill=tk.X, expand=True)
        gateway_entry.insert(0, config.get("gateway", ""))
        setattr(self, f"{network_type}_gateway_entry", gateway_entry)

        # DNS配置区域
        dns_frame = ttk.LabelFrame(parent, text="DNS服务器")
        dns_frame.pack(fill=tk.X, pady=10, expand=True)

        # 首选DNS
        dns1_frame = ttk.Frame(dns_frame)
        dns1_frame.pack(fill=tk.X, pady=frame_pack_pady)
        ttk.Label(dns1_frame, text="首选DNS:", width=label_width).pack(side=tk.LEFT)
        dns1_entry = ttk.Entry(dns1_frame, width=entry_width)
        dns1_entry.pack(side=tk.LEFT, padx=entry_pack_padx, fill=tk.X, expand=True)
        dns1_entry.insert(0, config.get("dns1", ""))
        setattr(self, f"{network_type}_dns1_entry", dns1_entry)

        # 备用DNS
        dns2_frame = ttk.Frame(dns_frame)
        dns2_frame.pack(fill=tk.X, pady=frame_pack_pady)
        ttk.Label(dns2_frame, text="备用DNS:", width=label_width).pack(side=tk.LEFT)
        dns2_entry = ttk.Entry(dns2_frame, width=entry_width)
        dns2_entry.pack(side=tk.LEFT, padx=entry_pack_padx, fill=tk.X, expand=True)
        dns2_entry.insert(0, config.get("dns2", ""))
        setattr(self, f"{network_type}_dns2_entry", dns2_entry)

        # 初始状态
        self.toggle_config_fields(network_type)

    def toggle_config_fields(self, network_type):
        """切换配置字段的可用状态"""
        dhcp_var = getattr(self, f"{network_type}_dhcp_var")
        state = "disabled" if dhcp_var.get() else "!disabled"

        for field in ["ip", "mask", "gateway", "dns1", "dns2"]:
            entry = getattr(self, f"{network_type}_{field}_entry")
            entry.state([state])

    def get_config_data(self, network_type):
        """从界面获取配置数据"""
        dhcp_var = getattr(self, f"{network_type}_dhcp_var")
        config = {"dhcp": dhcp_var.get()}

        if not dhcp_var.get():
            # 获取所有字段值
            ip = getattr(self, f"{network_type}_ip_entry").get().strip()
            mask = getattr(self, f"{network_type}_mask_entry").get().strip()
            gateway = getattr(self, f"{network_type}_gateway_entry").get().strip()
            dns1 = getattr(self, f"{network_type}_dns1_entry").get().strip()
            dns2 = getattr(self, f"{network_type}_dns2_entry").get().strip()

            config.update(
                {"ip": ip, "mask": mask, "gateway": gateway, "dns1": dns1, "dns2": dns2}
            )

        return config

    def save_all_configs(self):
        """保存所有配置"""
        # 保存内网配置
        internal_config = self.get_config_data("internal")
        internal_success, internal_msg = self.controller.save_network_config("internal", internal_config)

        # 保存外网配置
        external_config = self.get_config_data("external")
        external_success, external_msg = self.controller.save_network_config("external", external_config)

        if internal_success and external_success:
            messagebox.showinfo("成功", "内网和外网配置已保存")
            self.close_view()
        else:
            error_msg = ""
            if not internal_success:
                error_msg += f"内网配置错误: {internal_msg}\n"
            if not external_success:
                error_msg += f"外网配置错误: {external_msg}"

            messagebox.showerror("错误", error_msg)

    def center_window(self):
        """将窗口居中显示（仅独立窗口模式）"""
        if not hasattr(self, "top"):
            return

        self.top.update_idletasks()
        width = self.top.winfo_width()
        height = self.top.winfo_height()
        x = (self.top.winfo_screenwidth() // 2) - (width // 2)
        y = (self.top.winfo_screenheight() // 2) - (height // 2)
        self.top.geometry(f"+{x}+{y}")

    def bind_mousewheel(self):
        # 绑定Windows和macOS的滚轮事件
        self.canvas.bind("<MouseWheel>", self._on_mousewheel)
        # 绑定Linux的滚轮事件（Button-4是向上滚动，Button-5是向下滚动）
        self.canvas.bind("<Button-4>", self._on_mousewheel_linux)
        self.canvas.bind("<Button-5>", self._on_mousewheel_linux)

        # 递归绑定可滚动区域内的所有控件
        self._bind_mousewheel_recursive(self.scrollable_frame)

    def _bind_mousewheel_recursive(self, widget):
        """递归绑定鼠标滚轮事件到控件及其子控件"""
        # 绑定事件
        widget.bind("<MouseWheel>", self._on_mousewheel)
        widget.bind("<Button-4>", self._on_mousewheel_linux)
        widget.bind("<Button-5>", self._on_mousewheel_linux)

        # 递归绑定所有子控件
        for child in widget.winfo_children():
            self._bind_mousewheel_recursive(child)

    def _on_mousewheel(self, event):
        """处理鼠标滚轮事件（Windows/macOS）"""
        # Windows/macOS: event.delta通常为120或-120
        # 处理更平滑的滚动
        if event.delta:
            scroll_amount = -1 * (event.delta // 120)  # 每120单位滚动一行
            if scroll_amount == 0:  # 处理小幅度滚动
                scroll_amount = -1 if event.delta > 0 else 1
        else:
            return  # 如果没有delta值，直接返回

        self.canvas.yview_scroll(scroll_amount, "units")
        return "break"  # 阻止事件继续传播

    def _on_mousewheel_linux(self, event):
        """处理鼠标滚轮事件（Linux）"""
        # Linux: event.num为4表示向上滚动，5表示向下滚动
        if event.num == 4:
            self.canvas.yview_scroll(-1, "units")  # 向上滚动一行
        elif event.num == 5:
            self.canvas.yview_scroll(1, "units")  # 向下滚动一行
        return "break"  # 阻止事件继续传播

    def close_view(self):
        """关闭视图"""
        if hasattr(self, "top"):
            # 独立窗口模式：销毁整个窗口
            self.top.destroy()
        else:
            # 内嵌模式：销毁框架
            self.frame.destroy()